#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <random>
#include <vector>
#define N 500001
#define M 10000000
#define W 65535
#define Z 16777215
using namespace std;
mt19937 RAND(random_device{}());
int read() {
    char c = 0;
    int sum = 0;
    while (c < '0' || c > '9') c = getchar();
    while ('0' <= c && c <= '9') sum = sum * 10 + c - '0', c = getchar();
    return sum;
}
void write(__int128 x) {
    if (0 <= x && x <= 9) {
        printf("%d", (int)(x));
        return;
    }
    write(x / 10), printf("%d", (int)(x % 10));
    return;
}
int gcd(int x, int y) {
    if (!y) return x;
    return gcd(y, x % y);
}
int lcm(int x, int y) { return x / gcd(x, y) * y; }
int n, q, p, sx, sy, len, slen[N + 1], rd[W + 1], rd2[W + 1], rd3[W + 1],
    rd4[W + 1], tong[N + 1], length, kr[N + 1], kp[N + 1], kd[N + 1],
    head[Z + 1], a[N + 1], b[N + 1], wcnt[N + 1], tr, tp;
bool op;
struct reads {
    int zr, zp, data;
};
vector<reads> p1[N + 1];
vector<reads> p2[N + 1];
struct node {
    int x, y;
    long long data;
    __int128 data2;
    int nxt;
};
node edge[M + 1];
void adder_hsh(int x, int y, int d) {
    int ds = rd[x & W] ^ rd2[x >> 16] ^ rd3[y & W] ^ rd4[y >> 16];
    for (int i = head[ds]; i > 0; i = edge[i].nxt)
        if (edge[i].x == x && edge[i].y == y) {
            edge[i].data += d;
            return;
        }
    edge[++len] = (node){x, y, d, 0, head[ds]}, head[ds] = len;
    return;
}
void adder_hsh2(int x, int y, long long d) {
    int ds = rd[x & W] ^ rd2[x >> 16] ^ rd3[y & W] ^ rd4[y >> 16];
    for (int i = head[ds]; i > 0; i = edge[i].nxt)
        if (edge[i].x == x && edge[i].y == y) {
            edge[i].data2 += d;
            return;
        }
    edge[++len] = (node){x, y, 0, d, head[ds]}, head[ds] = len;
    return;
}
long long query_hsh(int x, int y) {
    int ds = rd[x & W] ^ rd2[x >> 16] ^ rd3[y & W] ^ rd4[y >> 16];
    for (int i = head[ds]; i > 0; i = edge[i].nxt)
        if (edge[i].x == x && edge[i].y == y) return edge[i].data;
    return 0;
}
__int128 query_hsh2(int x, int y) {
    int ds = rd[x & W] ^ rd2[x >> 16] ^ rd3[y & W] ^ rd4[y >> 16];
    for (int i = head[ds]; i > 0; i = edge[i].nxt)
        if (edge[i].x == x && edge[i].y == y) return edge[i].data2;
    return 0;
}
void exgcd(int x, int y) {
    if (!y) {
        sx = 1, sy = 0;
        return;
    }
    exgcd(y, x % y);
    int zx = sx;
    sx = sy, sy = zx - x / y * sy;
    return;
}
int get_inv(int x, int sp) {
    exgcd(x, sp);
    return (sx % sp + sp) % sp;
}
void insert(int x, int sp) {
    if (sp == tp) {
        if (tr != x) op = 1;
        return;
    }
    if ((x - tr) % gcd(tp, sp) != 0) {
        op = 1;
        return;
    }
    int ds = (x - tr) / gcd(tp, sp), wp = lcm(tp, sp);
    exgcd(tp, sp), sx = (sx % sp + sp) % sp;
    long long dz = 1ll * (1ll * sx * ds % wp) * tp + tr;
    tr = (dz % wp + wp) % wp, tp = wp;
    return;
}
void append(int x, int y) {
    int d = gcd(x, p), sp;
    if (y % d != 0) {
        op = 1;
        return;
    }
    x /= d, y /= d, sp = p / d, insert(1ll * y * get_inv(x, sp) % sp, sp);
    return;
}
void adder(int x) {
    if (p1[x].empty() || p1[x].back().zp != tp)
        p1[x].push_back((reads){tr, tp, 1});
    else
        p1[x].back().data++;
    return;
}
void adder2(int x) {
    if (p2[x].empty() || p2[x].back().zp != tp)
        p2[x].push_back((reads){tr, tp, 1});
    else
        p2[x].back().data++;
    return;
}
void solve() {
    int g, g2, d, dr, wp, ps = 0, rst;
    for (int i = 1; i <= n; ++i) {
        op = 0;
        if (ps + slen[ps] >= i) {
            p1[i] = p1[(ps << 1) - i],
            slen[i] = min(slen[(ps << 1) - i], ps + slen[ps] - i),
            rst = slen[(ps << 1) - i] - slen[i];
            while (rst) {
                d = min(p1[i].back().data, rst), p1[i].back().data -= d,
                rst -= d;
                if (!p1[i].back().data) p1[i].pop_back();
            }
            tr = p1[i].back().zr, tp = p1[i].back().zp;
        } else
            tr = 0, tp = 1, adder(i);
        while (slen[i] + 1 <= min(i - 1, n - i)) {
            append((a[i - slen[i] - 1] - a[i - slen[i]] + p) % p,
                   (a[i + slen[i] + 1] - a[i + slen[i]] + p) % p);
            if (op) break;
            append((a[i + slen[i] + 1] - a[i + slen[i]] + p) % p,
                   (a[i - slen[i] - 1] - a[i - slen[i]] + p) % p);
            if (op) break;
            slen[i]++, adder(i);
        }
        if (i + slen[i] > ps + slen[ps]) ps = i;
    }
    ps = 0;
    for (int i = 1; i <= n - 1; ++i) {
        slen[i] = -1, op = 0;
        if (ps + slen[ps] >= i) {
            p2[i] = p2[(ps << 1) - i],
            slen[i] = min(slen[(ps << 1) - i], ps + slen[ps] - i),
            rst = slen[(ps << 1) - i] - slen[i];
            while (rst) {
                d = min(p2[i].back().data, rst), p2[i].back().data -= d,
                rst -= d;
                if (!p2[i].back().data) p2[i].pop_back();
            }
            tr = p2[i].back().zr, tp = p2[i].back().zp;
        } else {
            tr = 0, tp = 1,
            append((a[i] - a[i + 1] + p) % p, (a[i + 1] - a[i] + p) % p);
            if (op) continue;
            slen[i] = 0, adder2(i);
        }
        while (slen[i] + 1 <= min(i - 1, n - i - 1)) {
            append((a[i - slen[i] - 1] - a[i - slen[i]] + p) % p,
                   (a[i + slen[i] + 2] - a[i + slen[i] + 1] + p) % p);
            if (op) break;
            append((a[i + slen[i] + 2] - a[i + slen[i] + 1] + p) % p,
                   (a[i - slen[i] - 1] - a[i - slen[i]] + p) % p);
            if (op) break;
            slen[i]++, adder2(i);
        }
        if (i + slen[i] > ps + slen[ps]) ps = i;
    }
    for (int i = 1; i <= n; ++i)
        for (int j = 0; j < p1[i].size(); ++j)
            adder_hsh(p1[i][j].zp, p1[i][j].zr, p1[i][j].data);
    for (int i = 1; i <= n - 1; ++i)
        for (int j = 0; j < p2[i].size(); ++j)
            adder_hsh(p2[i][j].zp, p2[i][j].zr, p2[i][j].data);
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < p1[i].size(); ++j)
            g = gcd(a[i], p), wp = p / g, g2 = gcd(wp, p1[i][j].zp),
            dr = (1ll * (a[i] / g) * (1 - p1[i][j].zr) % g2 + g2) % g2,
            kr[j] = dr * g, kp[j] = g * g2, kd[j] = p / lcm(wp, p1[i][j].zp);
        for (int j = 0; j < p1[i].size(); ++j)
            adder_hsh2(kp[j], kr[j], 1ll * p1[i][j].data * kd[j]);
    }
    for (int i = 1; i <= n - 1; ++i) {
        for (int j = 0; j < p2[i].size(); ++j)
            g = gcd(a[i], p), wp = p / g, g2 = gcd(wp, p2[i][j].zp),
            dr = (1ll * (a[i] / g) * p2[i][j].zr % g2 + g2) % g2,
            kr[j] = ((a[i + 1] - dr * g) % (g * g2) + (g * g2)) % (g * g2),
            kp[j] = g * g2, kd[j] = p / lcm(wp, p2[i][j].zp);
        for (int j = 0; j < p2[i].size(); ++j)
            adder_hsh2(kp[j], kr[j], 1ll * p2[i][j].data * kd[j]);
    }
    return;
}
long long query(int x) {
    long long res = 0;
    for (int i = 1; i <= length; ++i) res += query_hsh(tong[i], x % tong[i]);
    return res;
}
__int128 query2(int x) {
    __int128 res = 0;
    for (int i = 1; i <= length; ++i) res += query_hsh2(tong[i], x % tong[i]);
    return res;
}
int main() {

    freopen("string.in", "r", stdin);
    freopen("string.out", "w", stdout);
    int op, x;
    for (int i = 0; i < W; ++i)
        rd[i] = RAND() & Z, rd2[i] = RAND() & Z, rd3[i] = RAND() & Z,
        rd4[i] = RAND() & Z;
    n = read(), q = read(), p = read();
    for (int i = 1; i * i <= p; ++i)
        if (p % i == 0) {
            tong[++length] = i;
            if (i * i != p) tong[++length] = p / i;
        }
    for (int i = 1; i <= n; ++i) a[i] = read();
    solve();
    while (q--) {
        op = read(), x = read();
        if (op == 1)
            printf("%lld\n", query(x));
        else
            write(query2(x)), puts("");
    }
    return 0;
}
